package com.osdp.common.log.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@Component
@Slf4j
@Aspect
public class LogAspect {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Pointcut("@annotation(com.osdp.common.annotation.Log)")
    public void logPointcut(){

    }
    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        log.info(String.format("[%s] [METHOD:%s] [URL:%s] [IP:%s] [%s]", "REQUEST", request.getMethod(), request.getRequestURL().toString(),
                request.getRemoteAddr(), getParams(joinPoint, request)));
        //出参
        long startTime = System.currentTimeMillis();
        Object retVal = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        log.info(String.format("[%s] [RESPONSE BODY:%s] [TIME:%sms]", "RESPONSE", objectMapper.writeValueAsString(retVal), endTime - startTime));
        return retVal;
    }

    private String getParams(JoinPoint joinPoint, HttpServletRequest request) throws JsonProcessingException {
        Map<String, Object> map = Maps.newHashMap();
        map.put("REQUEST BODY", joinPoint.getArgs());
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return objectMapper.writeValueAsString(map);
    }
}
